#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <iostream>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include<fcntl.h>

char *test_start_address = NULL;
int test_start_size = 0;
char *test_end_address = NULL;
int test_end_size = 0;
char *test_file_address = NULL;
int test_file_size = 0;
//const char *test_start_file = "/home/yeq/test_start.txt";
const char *test_start_file = "/mnt/ramfs/test_start.txt";
const char *test_end_file = "/home/yeq/test_end.txt";
const char *test_file = "/mnt/ramfs/test.tar.gz";

int thread_number = 100;
int port = 8080;
char* ip = NULL;

int test_size = 1024;

const int write_buff_size = 1024;

void * work(void *address)
{
	//char *start_address = (char*)address;
	int fd,ret;
    struct sockaddr_in addr = {0};
    struct in_addr x;
    inet_aton(ip,&x);
    addr.sin_family = AF_INET;
    addr.sin_addr = x;
    addr.sin_port = htons(port);
    fd = socket(AF_INET,SOCK_STREAM,0);
	
	int write_count = 0;
	int temp = 0;
	
	char buff[1024] = {'\0'};
	char write_buff[write_buff_size] = {'a'};
	
    if(fd == -1)
    {
        printf("fd error\n");
        return NULL;
    }
	
    ret = connect(fd,(sockaddr*)&addr,sizeof(addr));
    if(ret == -1)
    {
        printf("connect error\n");
        goto error;
    }
	
	
	 //printf("start send\n");
	  //printf("writecount:%d\tteststartsize:%d\n",write_count, test_start_size);
	  
	//write test start
	while (1) {
		//printf("while send\n");
		if (write_count >= test_start_size) {
			printf("break\n");
			break;
		}
		
		//printf("sending %d\n", write_count);
		
		temp = write(fd , test_start_address + write_count,
				test_start_size - write_count);
				
		if (temp <= -1) {
			printf("test error:%d\n", errno);
			goto error;
		}
		
		if (temp == 0) {
			printf("peer closed:%d\n", errno);
			goto error;
		}

		write_count += temp;
		if (write_count >= test_start_size) {
			//printf("test ok\n");
			break;
		}
	}
	
	/*
	//write content
	for(int i = 0; i< test_size; i++)
	{
				temp = 0;
				write_count = 0;
				while (1) {
		if (write_count >= test_file_size) {
			break;
		}
		
		temp = write(fd , test_file_address + write_count,
				test_file_size - write_count);
				
		if (temp <= -1) {
			printf("test error:%d\n", errno);
			goto error;
		}
		
		if (temp == 0) {
			printf("peer closed:%d\n", errno);
			goto error;
		}

		write_count += temp;
		if (write_count >= test_file_size) {
			//printf("test ok\n");
			break;
		}
	}
}
	
	printf("content OK\n");

	//write test end
	temp = 0;
	write_count = 0;
	while (1) {
		if (write_count >= test_end_size) {
			break;
		}
		
		temp = write(fd , test_end_address + write_count,
				test_end_size - write_count);
				
		if (temp <= -1) {
			printf("test error:%d\n", errno);
			goto error;
		}
		
		if (temp == 0) {
			printf("peer closed:%d\n", errno);
			goto error;
		}

		write_count += temp;
		if (write_count >= test_end_size) {
			//printf("test ok\n");
			break;
		}
	}
	*/

	temp = 0;
	temp = read(fd, buff, 1024) ;
	//printf("buff:%s\n",buff);
	
	error:
	close(fd);
	return NULL;
}

int main(int argc, char *argv[])
{
	if (argc <= 4) {
		printf("usage: %s ip_address port_number thread_number testsize(KB),\n", basename(argv[0]));
		return 1;
	}
	
	ip = argv[1];
	int port = atoi(argv[2]);
	thread_number = atoi(argv[3]);
	test_size = atoi(argv[4]);
	
	struct stat m_file_stat;
	//const char *file_name = "/home/yeq/test.txt";
	stat(test_start_file, &m_file_stat) ;
	test_start_size = m_file_stat.st_size;
	printf("test_start_size:%d\n",test_start_size);
	
	/*
	stat(test_end_file, &m_file_stat) ;
	int test_end_size = m_file_stat.st_size;
	
	stat(test_file, &m_file_stat) ;
	int test_file_size = m_file_stat.st_size;
	 * */
	
	int test_file_id = open(test_start_file, O_RDONLY);
	test_start_address = (char*) mmap(0, test_start_size, PROT_READ,
	MAP_PRIVATE, test_file_id, 0);
	close(test_file_id);
	
	/*
	test_file_id = open(test_end_file, O_RDONLY);
	char *test_end_address = (char*) mmap(0, test_end_size, PROT_READ,
	MAP_PRIVATE, test_file_id, 0);
	close(test_file_id);
	
	test_file_id = open(test_file, O_RDONLY);
	char *test_file_address = (char*) mmap(0, test_file_size, PROT_READ,
	MAP_PRIVATE, test_file_id, 0);
	close(test_file_id);
	 * */
	
	pthread_t *m_threads = new pthread_t[thread_number];
	for (int i = 0; i < thread_number; ++i) {
		
		if (pthread_create(m_threads + i, NULL, work, NULL) != 0) {
			printf("pthread_create error ok\n");
			delete[] m_threads;
			return -1;
		}
	}
	
	for (int i = 0; i < thread_number; ++i) {
		pthread_join(m_threads[i], NULL);
	}
	
	printf("test all ok\n");
}

